home *** CD-ROM | disk | FTP | other *** search
/ LiquidLibrary 2005 September / LiquidLibrary 2005 Sep - Disc 1.iso / pc / Portfolio Browser / Filters / PDF / LIB / pdf_draw.ps < prev    next >
Text File  |  2003-01-03  |  35KB  |  1,141 lines

  1. %    Copyright (C) 1994, 2000 Aladdin Enterprises.  All rights reserved.
  2. % This software is licensed to a single customer by Artifex Software Inc.
  3. % under the terms of a specific OEM agreement.
  4.  
  5. % $RCSfile$ $Revision$
  6. % pdf_draw.ps
  7. % PDF drawing operations (graphics, text, and images).
  8.  
  9. /.setlanguagelevel where { pop 2 .setlanguagelevel } if
  10. .currentglobal true .setglobal
  11. /pdfdict where { pop } { /pdfdict 100 dict def } ifelse
  12. GS_PDF_ProcSet begin
  13. pdfdict begin
  14.  
  15. % For simplicity, we use a single interpretation dictionary for all
  16. % PDF graphics operations, even though this is too liberal.
  17. /drawopdict 100 dict def
  18.  
  19. % ================================ Graphics ================================ %
  20.  
  21. % ---------------- Functions ---------------- %
  22.  
  23. % Note that resolvefunction converts a PDF Function to a PostScript Function;
  24. % resolve*fnproc converts a PDF function to a PostScript procedure.
  25.  
  26. /fnrdict mark
  27.   0 { .resolvefn0 }
  28.   2 { }
  29.   3 { .resolvefn3 }
  30.   4 { .resolvefn4 }
  31. .dicttomark readonly def
  32.  
  33. /.resolvefn0 {
  34.         % Don't lose our place in PDFfile.
  35.   PDFfile fileposition exch
  36.   dup true resolvestream
  37.         % The stream isn't positionable, so read all the data now.
  38.         % Stack: filepos fndict stream
  39.   1 index /Range oget length 2 idiv 2 index /BitsPerSample oget mul
  40.   2 index /Size oget { mul } forall
  41.   7 add 8 idiv string
  42.   1 index exch readstring pop exch closefile
  43.         % Stack: filepos fndict data
  44.   exch dup length 1 add dict .copydict
  45.   dup /DataSource 4 -1 roll put
  46.   exch PDFfile exch setfileposition
  47. } bdef
  48.  
  49. /.resolvefn3 {
  50.   dup length dict .copydict
  51.   dup /Bounds 2 copy knownoget { put } { pop pop } ifelse
  52.   dup /Encode 2 copy knownoget { put } { pop pop } ifelse
  53.   dup /Functions 2 copy oget mark exch dup {
  54.     oforce .resolvefn
  55.   } forall
  56.   counttomark -1 roll astore exch pop put
  57. } bdef
  58.  
  59. /.resolvefn4 {
  60.   PDFfile fileposition exch             % filepos fndict
  61.   dup true resolvestream                % filepos fndict stream
  62.   exch dup length dict copy             % filepos stream fndict2
  63.   dup /Function undef                   % filepos stream fndict2
  64.   exch dup token not {
  65.     () /rangecheck cvx signalerror
  66.   } if
  67.   exch token {
  68.     /rangecheck cvx signalerror
  69.   } if
  70.         % Use .bind to avoid idiom recognition.
  71.   .bind
  72.   1 index /Function 3 -1 roll put
  73.   exch PDFfile exch setfileposition
  74. } bdef
  75. currentdict /tfopdict undef
  76.  
  77. /.resolvefn {        % <fndict> .resolvefn <fndict'>
  78.   dup /FunctionType oget //fnrdict exch get exec
  79. } bdef
  80.  
  81. /resolvefunction {    % <fndict> resolvefunction <function>
  82.   .resolvefn
  83.   DEBUG { (%Function: ) print dup === flush } if
  84. } bdef
  85.  
  86. /resolvefnproc {    % <fndict> resolvefnproc <proc>
  87.   resolvefunction .buildfunction
  88. } bdef
  89.  
  90. /resolveidfnproc {    % <fndict> resolveidfnproc <proc>
  91.   dup /Identity eq { pop { } } { resolvefnproc } ifelse
  92. } bdef
  93.  
  94. /resolvedefaultfnproc {    % <fndict> <default> resolved'fnproc <proc>
  95.   1 index /Default eq { exch pop } { pop resolveidfnproc } ifelse
  96. } bdef
  97.  
  98. % ---------------- Shadings ---------------- %
  99.  
  100. /shrdict mark
  101.   /ColorSpace {
  102.     resolvecolorspace
  103.   }
  104.   /Function {
  105.     dup type /dicttype eq {
  106.       resolvefunction
  107.     } {
  108.       [ exch { oforce resolvefunction } forall ]
  109.     } ifelse
  110.   }
  111. .dicttomark readonly def
  112.  
  113. /resolveshading {    % <shadingstream> resolveshading <shading>
  114.   PDFfile fileposition exch
  115.   mark exch {
  116.     oforce //shrdict 2 index .knownget { exec } if
  117.   } forall .dicttomark
  118.   dup /ShadingType get 4 ge {
  119.     dup dup true resolvestream
  120.         % Make a reusable stream so that the shading doesn't
  121.         % reposition PDFfile at unexpected times.
  122.     /ReusableStreamDecode filter /DataSource exch put
  123.   } if exch PDFfile exch setfileposition
  124. } bdef
  125. /resolvesh {        % <shname> resolveshading <shading>
  126.   Page /Shading rget {
  127.     resolveshading
  128.   } {
  129.     null
  130.   }ifelse
  131. } bdef
  132.  
  133. % ---------------- Halftones ---------------- %
  134.  
  135. /spotfunctions mark
  136.   /Round {
  137.     abs exch abs 2 copy add 1 le {
  138.       dup mul exch dup mul add 1 exch sub 
  139.     } {
  140.       1 sub dup mul exch 1 sub dup mul add 1 sub
  141.     } ifelse
  142.   }
  143.   /Diamond {
  144.     abs exch abs 2 copy add .75 le {
  145.       dup mul exch dup mul add 1 exch sub
  146.     } {
  147.       2 copy add 1.23 le {
  148.     .85 mul add 1 exch sub
  149.       } {
  150.     1 sub dup mul exch 1 sub dup mul add 1 sub
  151.       } ifelse
  152.     } ifelse
  153.   }
  154.   /Ellipse {
  155.     abs exch abs 2 copy 3 mul exch 4 mul add 3 sub dup 0 lt {
  156.       pop dup mul exch .75 div dup mul add 4 div 1 exch sub
  157.     } {
  158.       dup 1 gt {
  159.     pop 1 exch sub dup mul exch 1 exch sub
  160.     .75 div dup mul add 4 div 1 sub
  161.       } {
  162.     .5 exch sub exch pop exch pop
  163.       } ifelse
  164.     } ifelse
  165.   }
  166.   /EllipseA { dup mul .9 mul exch dup mul add 1 exch sub }
  167.   /InvertedEllipseA { dup mul .9 mul exch dup mul add 1 sub }
  168.   /EllipseB { dup 5 mul 8 div mul exch dup mul exch add sqrt 1 exch sub }
  169.   /EllipseC { dup mul .9 mul exch dup mul add 1 exch sub }
  170.   /InvertedEllipseC { dup mul .9 mul exch dup mul add 1 sub }
  171.   /Line { exch pop abs neg }
  172.   /LineX { pop }
  173.   /LineY { exch pop }
  174.   /Square { abs exch abs 2 copy lt { exch } if pop neg }
  175.   /Cross { abs exch abs 2 copy gt { exch } if pop neg }
  176.   /Rhomboid { abs exch abs 0.9 mul add 2 div }
  177.   /DoubleDot { 2 {360 mul sin 2 div exch } repeat add }
  178.   /InvertedDoubleDot { 2 {360 mul sin 2 div exch } repeat add neg }
  179.   /SimpleDot { dup mul exch dup mul add 1 exch sub }
  180.   /InvertedSimpleDot { dup mul exch dup mul add 1 sub }
  181.   /CosineDot { 180 mul cos exch 180 mul cos add 2 div }
  182.   /Double { exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add }
  183.   /InvertedDouble {
  184.     exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add neg
  185.   }
  186. .dicttomark readonly def
  187.  
  188. /htrdict mark
  189.   1 { .resolveht1 }
  190.   5 { .resolveht5 }
  191.     % We don't support types 6, 10, or 16 yet.
  192. .dicttomark readonly def
  193.  
  194. /.resolveht1 {
  195.   mark exch {
  196.     oforce
  197.     1 index /SpotFunction eq {
  198.       dup type /nametype eq
  199.     { //spotfunctions exch get } { resolvefnproc }
  200.       ifelse
  201.     } {
  202.       1 index /TransferFunction eq {
  203.     resolveidfnproc
  204.       } if
  205.     } ifelse
  206.   } forall .dicttomark
  207. } bdef
  208.  
  209. /.resolveht5 {
  210.   mark exch {
  211.     oforce dup type /dicttype eq { resolvehalftone } if
  212.   } forall .dicttomark
  213. } bdef
  214.  
  215. /resolvehalftone {    % <dict> resolvehalftone <halftone>
  216.   dup /HalftoneType get //htrdict exch get exec
  217. } bdef
  218.  
  219. % ---------------- Graphics state management ---------------- %
  220.  
  221. /cmmatrix matrix def
  222. drawopdict begin
  223.             % Graphics state stack
  224.   /q { q } def
  225.   /Q { Q } def
  226.             % Graphics state setting
  227.   /cm { //cmmatrix astore concat } def
  228.   /i /setflat load def
  229.   /J /setlinecap load def
  230.   /d /setdash load def
  231.   /j /setlinejoin load def
  232.   /w /setlinewidth load def
  233.   /M /setmiterlimit load def
  234.   /gs { gs } def
  235. end
  236.  
  237. % Each entry in this dictionary is
  238. %    <gsres> <value> -proc- <gsres>
  239. /gsbg {
  240.   /BGDefault load resolvedefaultfnproc setblackgeneration
  241. } bdef
  242. /gsucr {
  243.   /UCRDefault load resolvedefaultfnproc setundercolorremoval
  244. } bdef
  245. /gstr {
  246.   dup type /arraytype eq {
  247.     { oforce /TRDefault load resolvedefaultfnproc } forall
  248.     setcolortransfer
  249.   } {
  250.     /TRDefault load resolvedefaultfnproc settransfer
  251.   } ifelse
  252. } bdef
  253. /gsparamdict mark
  254.   /SA { setstrokeadjust }
  255.   /OP { 1 index /op known not { dup op } if OP }
  256.     % The PDF 1.3 specification says that the name /Default is only
  257.     % recognized for {BG,UCR,TR}2.  However, PDF 1.3 files produced
  258.     % by Adobe Acrobat Distiller 4.0 for Windows use the name /Default
  259.     % with the older keys, so we have to implement this.
  260.   /BG { 1 index /BG2 known { pop } { gsbg } ifelse }
  261.   /UCR { 1 index /UCR2 known { pop } { gsucr } ifelse }
  262.   /TR { 1 index /TR2 known { pop } { gstr } ifelse }
  263.   /HT {
  264.     dup /Default eq {
  265.       pop .setdefaultscreen
  266.     } {
  267.     %****** DOESN'T IMPLEMENT THE STREAM CASE YET ******
  268.       resolvehalftone sethalftone
  269.     } ifelse
  270.   }
  271.   /HTP {
  272.     % HTP may be present even if this isn't a DPS interpreter.
  273.     /sethalftonephase where { pop aload pop sethalftonephase } { pop } ifelse
  274.   }
  275.     % PDF 1.3
  276.   /Font { aload pop Tf }
  277.   /LW { setlinewidth }
  278.   /LC { setlinecap }
  279.   /LJ { setlinejoin }
  280.   /ML { setmiterlimit }
  281.   /D { aload pop setdash }
  282.   /RI { ri }
  283.   /op { op }
  284.   /OPM { OPM }
  285.   /BG2 { gsbg }
  286.   /UCR2 { gsucr }
  287.   /TR2 { gstr }
  288.   /FL { setflat }
  289.   /SM {
  290.     % SM may be present even if this is only a Level 2 interpreter.
  291.     /setsmoothness where { pop setsmoothness } { pop } ifelse
  292.   }
  293.     % PDF 1.4
  294.     % All of these require the "transparency" feature in the interpreter.
  295.   /ca { ca }
  296.   /CA { CA }
  297.   /SMask { gssmask }
  298.   /AIS { AIS }
  299.   /BM { BM }
  300.   /TK { TK }
  301. .dicttomark readonly def
  302. /gs {            % <gsres> gs -
  303.   Page /ExtGState rget {
  304.     % We keep the dictionary on the stack during the forall so that
  305.     % keys that interact with each other have access to it.
  306.     dup {
  307.       oforce exch gsparamdict exch .knownget { exec } { pop } ifelse
  308.     } forall pop
  309.   } if
  310. } bdef
  311.  
  312. % ------ Transparency support ------ %
  313.  
  314. /gssmask {
  315.   dup /None eq {
  316.     pop null
  317.   } {
  318.     % Preprocess the SMask value into a parameter dictionary for
  319.     % .begintransparencymask, with added /BBox and /Draw keys.
  320.     mark exch        % Stack: mark smaskdict
  321.     dup /S oget /Subtype exch 3 2 roll
  322.             % Stack: mark ... smaskdict
  323.     dup /BC knownoget { /Background exch 3 2 roll } if
  324.     dup /TR knownoget {
  325.       resolveidfnproc /TransferFunction exch 3 2 roll
  326.     } if    
  327.     dup /G oget dup /BBox oget /BBox exch 4 2 roll
  328.     /.execmaskgroup cvx 2 packedarray cvx /Draw exch 3 2 roll
  329.     pop .dicttomark
  330.   } ifelse SMask
  331. } bdef
  332.  
  333. % This procedure is called to actually render the soft mask.
  334. /.execmaskgroup {    % <masknum> <paramdict> <formdict> .execmaskgroup -
  335.     % Save our place in PDFfile, and do a gsave to avoid resetting
  336.     % the color space.
  337.   gsave PDFfile fileposition 4 1 roll
  338.     % We have to select the group's color space so that the
  339.     % background color will be interpreted correctly.
  340.   dup /Group oget /CS knownoget { csresolve setcolorspace } if
  341.   exch dup /BBox get aload pop .begintransparencymask {
  342.     dup /Resources knownoget { oforce } { 0 dict } ifelse
  343.     exch false resolvestream
  344.     .execgroup .endtransparencymask
  345.   } .internalstopped {
  346.     .discardtransparencymask stop
  347.   } if
  348.   PDFfile exch setfileposition grestore
  349. } bdef
  350. % Paint a Form+Group XObject, either for a transparency mask or for a Do.
  351. /.execgroup {        % <resdict> <stream> .execgroup -
  352.   gsave
  353.   1 .setopacityalpha 1 .setshapealpha
  354.   0 .inittransparencymask 1 .inittransparencymask
  355.   /Compatible .setblendmode
  356.     % Execute the body of the Form, similar to DoForm.
  357.   pdfopdict .pdfruncontext
  358.   grestore
  359. } bdef
  360.  
  361. /.beginformgroup {    % groupdict bbox .beginformgroup -
  362.   exch mark exch            % bbox mark groupdict
  363.   dup /CS knownoget { csresolve setcolorspace } if
  364.   dup /I knownoget { /Isolated exch 3 2 roll } if
  365.   dup /K knownoget { /Knockout exch 3 2 roll } if
  366.   pop .dicttomark
  367.         % Stack: bbox paramdict
  368.   exch aload pop
  369.   .begintransparencygroup
  370. } bdef
  371.  
  372. % .paintgroupform implements the Form PaintProc in the case where the
  373. % Form XObject dictionary includes a Group key.  See .paintform below.
  374. /.paintgroupform {    % <resdict> <stream> <formdict> .paintgroupform -
  375.   dup /Group oget exch /BBox oget
  376.         % Stack: resdict stream groupdict bbox
  377.   .beginformgroup {
  378.     .execgroup
  379.   } .internalstopped {
  380.     .discardtransparencygroup stop
  381.   } if .endtransparencygroup
  382. } bdef
  383.  
  384. % Make an ImageType 103 (soft-masked) image.
  385. /makesoftmaskimage {    % <datasource> <imagemask> <SMask> makesoftmaskimage
  386.             %   <datasource> <imagemask>, updates currentdict =
  387.             %   imagedict
  388.         % See the ImageType 3 case of makemaskimage below.
  389.         % SMask is a stream, another Image XObject.
  390.         % Stack: datasource imagemask(false) smaskstreamdict
  391.   PDFfile fileposition exch
  392.   dup /Matte knownoget { /Matte exch def } if
  393.   dup length dict makeimagedict pop
  394.         % In order to prevent the two data sources from being
  395.         % aliased, we need to make at least one a reusable stream.
  396.         % We pick the mask, since it's smaller (in case we need to
  397.         % read all its data now).
  398.         % Stack: datasource imagemask(false) savedpos
  399.         % maskdict is currentdict
  400.   /DataSource DataSource mark
  401.     /Intent 1
  402.     /AsyncRead true
  403.   .dicttomark .reusablestreamdecode def
  404.   PDFfile exch setfileposition
  405.   currentdict end currentdict end
  406.   5 dict begin
  407.   /ImageType 103 def
  408.   /DataDict exch def
  409.   dup /InterleaveType 3 put
  410.   DataDict /Matte .knownget {
  411.     /Matte exch def
  412.   } if
  413.   AlphaIsShape { /ShapeMaskDict } { /OpacityMaskDict } ifelse exch def
  414.   /ColorSpace DataDict /ColorSpace get def
  415. } bdef
  416.  
  417. % ---------------- Color setting ---------------- %
  418.  
  419. /01_1 [0 1] readonly def
  420. /01_3 [0 1 0 1 0 1] readonly def
  421. /01_4 [0 1 0 1 0 1 0 1] readonly def
  422.  
  423. % The keys here are resolved (PostScript, not PDF) color space names.
  424. /csncompdict mark
  425.   /DeviceGray { pop 1 }
  426.   /DeviceRGB { pop 3 }
  427.   /DeviceCMYK { pop 4 }
  428.   /CIEBasedA { pop 1 }
  429.   /CIEBasedABC { pop 3 }
  430.   /ICCBased { 1 oget /N oget }
  431.   /Separation { pop 1 }
  432.   /DeviceN { 1 oget length }
  433. .dicttomark readonly def
  434.  
  435. % Perhaps some of the values in the following need to be modified
  436. % depending on the WhitePoint value....
  437. /cslabinit mark
  438.   /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind]
  439.   /MatrixABC [1 1 1 1 0 0 0 0 -1]
  440.   /DecodeLMN [
  441.     {dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse
  442.      0.9505 mul} bind
  443.     {dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse
  444.      } bind
  445.     {dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse
  446.      1.0890 mul} bind
  447.   ]
  448. .dicttomark readonly def
  449.  
  450. /csrdict mark
  451.   /DeviceGray {
  452.     /DefaultGray Page /ColorSpace rget { exch pop resolvecolorspace } if
  453.   }
  454.   /DeviceRGB {
  455.     /DefaultRGB Page /ColorSpace rget { exch pop resolvecolorspace } if
  456.   }
  457.   /DeviceCMYK { }
  458.   /CalGray {
  459.     1 oget 6 dict begin
  460.     dup /Gamma knownoget {
  461.       /exp load 2 packedarray cvx /DecodeA exch def
  462.     } if
  463.     dup /BlackPoint knownoget { /BlackPoint exch def } if
  464.     dup /WhitePoint knownoget { /WhitePoint exch def } if
  465.     pop [ /CIEBasedA currentdict end ]
  466.   }
  467.   /CalRGB {
  468.     1 oget 6 dict begin
  469.     dup /Gamma knownoget {
  470.       [ exch { /exp load 2 packedarray cvx } forall
  471.       ] /DecodeABC exch def
  472.     } if
  473.     dup /Matrix knownoget { /MatrixABC exch def } if
  474.     dup /BlackPoint knownoget { /BlackPoint exch def } if
  475.     dup /WhitePoint knownoget { /WhitePoint exch def } if
  476.     pop [ /CIEBasedABC currentdict end ]
  477.   }
  478.   /CalCMYK {
  479.     pop /DeviceCMYK        % not defined by Adobe
  480.   }
  481.   /Lab {
  482.     1 oget 6 dict begin
  483.     dup /Range knownoget not { [-100 100 -100 100] } if
  484.     [0 100 null null null null] dup 2 4 -1 roll putinterval
  485.     /RangeABC exch def
  486.     //cslabinit { def } forall
  487.     dup /BlackPoint knownoget { /BlackPoint exch def } if
  488.     dup /WhitePoint knownoget { /WhitePoint exch def } if
  489.     pop [ /CIEBasedABC currentdict end ]
  490.   }
  491.   /ICCBased {
  492.     PDFfile fileposition exch
  493.     dup dup 1 oget
  494.     mark exch { oforce } forall .dicttomark
  495.     dup dup true resolvestream
  496.     /ReusableStreamDecode filter /DataSource exch put
  497.     1 exch put
  498.     exch PDFfile exch setfileposition
  499.   } bind
  500.   /Separation {
  501.     aload pop exch oforce resolvecolorspace exch oforce resolvefnproc
  502.     4 array astore
  503.   }
  504.   /DeviceN {
  505.     0 4 getinterval                    % ignore attributes
  506.     aload pop 3 -1 roll oforce
  507.     3 -1 roll oforce resolvecolorspace
  508.     3 -1 roll oforce resolvefnproc
  509.     4 array astore
  510.   }
  511.   /Indexed {
  512.     aload pop 3 -1 roll oforce resolvecolorspace
  513.         % If the underlying space is a Lab space, we must scale
  514.         % the output of the lookup table as part of DecodeABC.
  515.     dup dup type /arraytype eq { 0 get } if /CIEBasedABC eq {
  516.       dup 1 get /DecodeLMN known {
  517.     1 get dup length dict copy
  518.     begin /DecodeABC [ 0 2 4 {
  519.       RangeABC 1 index 1 add get RangeABC 2 index get sub /mul load
  520.       RangeABC 3 index get /add load
  521.       DecodeABC 6 -1 roll 2 idiv get [ 6 1 roll aload pop ] cvx
  522.     } for ] def
  523.     /RangeABC //01_3 def
  524.     currentdict end /CIEBasedABC exch 2 array astore
  525.       } if
  526.     } if
  527.     3 1 roll
  528.     oforce dup type /stringtype ne {
  529.         % The color lookup table is a stream.
  530.         % Get its contents.  Don't lose our place in PDFfile.
  531.         % Stack: /Indexed basespace hival lookup
  532.     PDFfile fileposition 5 1 roll true resolvestream
  533.         % Stack: filepos /Indexed basespace hival lookupstream
  534.     1 index 1 add
  535.         % Stack: filepos /Indexed basespace hival lookupstream len
  536.     3 index
  537.       dup dup type /arraytype eq { 0 get } if
  538.       //csncompdict exch get exec mul
  539.     string readstring pop
  540.         % Stack: filepos /Indexed basespace hival table
  541.     5 -1 roll PDFfile exch setfileposition
  542.     }
  543.     if 4 array astore
  544.   }
  545.   /Pattern {
  546.     dup type /nametype ne {
  547.       dup length 1 gt {
  548.     1 oget resolvecolorspace
  549.     /Pattern exch 2 array astore
  550.       } if
  551.     } if
  552.   }
  553. .dicttomark readonly def
  554.  
  555. /cssubst {        % <csname> cssubst <cspace'> true
  556.             % <csname> cssubst false
  557.   dup resolvecolorspace
  558.   dup 1 index ne { exch pop true } { pop pop false } ifelse
  559. } bdef
  560.  
  561. /csnames mark
  562.   /DeviceGray dup  /DeviceRGB dup  /DeviceCMYK dup  /Pattern dup
  563. .dicttomark readonly def
  564. /csresolve {        % <csresourcename> csresolve <cspace>
  565.   dup Page /ColorSpace rget {
  566.     exch pop resolvecolorspace
  567.   } {
  568.     //csnames 1 index known not { /undefined cvx signalerror } if
  569.   } ifelse
  570. } bdef
  571. /resolvecolorspace {    % <cspace> resolvecolorspace <cspace'>
  572.   dup dup type /arraytype eq { 0 get } if
  573.   //csrdict exch .knownget {
  574.     exec dup type /nametype ne { dup length 1 eq { 0 get } if } if
  575.   } {
  576.     csresolve
  577.   } ifelse
  578. } bdef
  579.  
  580. /scresolve {    % <c0> ... scresolve <multi>
  581.         % We can't really make sc[n] and SC[N] work, because
  582.         % the color space information isn't available at
  583.         % conversion time; so we hack it by assuming that
  584.         % all the operands on the stack are used, and that
  585.         % if the top operand is a name, it's a Pattern resource.
  586.   dup type /nametype eq
  587.     { Page /Pattern rget { resolvepattern } { null } ifelse }
  588.   if
  589.   dup type /dicttype eq {
  590.         % Check the PaintType, if any (shading patterns don't
  591.         % have one).
  592.     dup /PaintType .knownget { 2 eq } { false } ifelse
  593.   } {
  594.     .pdfcount 1 gt
  595.   } ifelse
  596. } bdef
  597.  
  598. /.pdfpaintproc {         % <patdict> <resdict> .pdfpaintproc -
  599.   DEBUG { (%Begin PaintProc) = flush } if
  600.     % For uncolored patterns, we have to unbind the current
  601.     % color and color space before running the PaintProc.
  602.     % There's no harm in doing this for colored patterns,
  603.     % so for simplicity, we always do it.
  604.   PDFfile fileposition 3 1 roll
  605.   q
  606.   null sc1 null SC1
  607.   exch false resolvestream pdfopdict .pdfruncontext
  608.   Q
  609.   DEBUG { (%End PaintProc) = flush } if
  610.   PDFfile exch setfileposition
  611. } bdef
  612.  
  613. /resolvepattern {    % <patternstreamdict> resolvepattern <patterndict>
  614.         % Don't do the resolvestream now: just capture the data
  615.         % from the file if necessary.
  616.   dup length dict copy
  617.   dup /FilePosition .knownget {
  618.     1 index /File get dup fileposition 3 1 roll
  619.         % Stack: dict savepos pos file
  620.     dup 3 -1 roll setfileposition
  621.     dup 3 index /Length oget string readstring pop
  622.         % Stack: dict savepos file string
  623.     3 1 roll exch setfileposition
  624.     1 index /File 3 -1 roll put
  625.     dup /FilePosition undef
  626.   } if
  627.   dup /Shading knownoget {
  628.     resolveshading 1 index /Shading 3 -1 roll put
  629.   } if
  630.   dup /PaintProc [
  631.         % Bind the resource dictionary into the PaintProc.
  632.     2 index /Resources knownoget { oforce } { 0 dict } ifelse
  633.     /.pdfpaintproc cvx
  634.   ] cvx put
  635.   DEBUG {
  636.     (%Pattern: ) print dup === flush
  637.   } if
  638. } bdef
  639.  
  640. drawopdict begin
  641.   /g { /DeviceGray cssubst { cs sc1 } { g } ifelse } bdef
  642.   /rg { /DeviceRGB cssubst { cs sc* } { rg } ifelse } bdef
  643.   /k { k } bdef
  644.   /cs { csresolve cs } bdef
  645.   /sc { scresolve { sc* } { sc1 } ifelse } bdef
  646.   /scn /sc load def
  647.   /G { /DeviceGray cssubst { CS SC1 } { G } ifelse } bdef
  648.   /RG { /DeviceRGB cssubst { CS SC* } { RG } ifelse } bdef
  649.   /K { K } bdef
  650.   /CS { csresolve CS } bdef
  651.   /ri { ri } bdef
  652.   /SC { scresolve { SC* } { SC1 } ifelse } bdef
  653.   /SCN /SC load def
  654. end
  655.  
  656. % ---------------- Paths ---------------- %
  657.  
  658. drawopdict begin
  659.             % Path construction
  660.   /m /moveto load def
  661.   /l /lineto load def
  662.   /c /curveto load def
  663.   /v { currentpoint 6 2 roll curveto } def
  664.   /y { 2 copy curveto } def
  665.   /re {
  666.    4 2 roll moveto  exch dup 0 rlineto  0 3 -1 roll rlineto  neg 0 rlineto
  667.    closepath
  668.   } def
  669.   /h /closepath load def
  670.             % Path painting and clipping
  671.   /n { n } def
  672.   /S { S } def
  673.   /s { s } def
  674.   /f { f } def
  675.   /f* { f* } def
  676.   /B { B } def
  677.   /b { b } def
  678.   /B* { B* } def
  679.   /b* { b* } def
  680.   /W { W } def
  681.   /W* { W* } def
  682.   /sh { resolvesh shfill } def
  683. end
  684.  
  685. % ---------------- XObjects ---------------- %
  686.  
  687. /xobjectprocs mark        % <dict> -proc- -
  688.   /Image { DoImage }
  689.   /Form { DoForm }
  690.   /PS { DoPS }
  691. .dicttomark readonly def
  692.  
  693. % Note that the keys in defaultdecodedict are resolved (PostScript, not PDF)
  694. % color space names.
  695. /defaultdecodedict mark
  696.   /DeviceGray { pop //01_1 } bind
  697.   /DeviceRGB { pop //01_3 } bind
  698.   /DeviceCMYK { pop //01_4 } bind
  699.   /CIEBasedA { 1 get /RangeA .knownget not { //01_1 } if } bind
  700.   /CIEBasedABC { 1 get /RangeABC .knownget not { //01_3 } if } bind
  701.   /ICCBased {
  702.      1 oget dup /Range .knownget {
  703.        exch pop
  704.      }{
  705.        /N get [ exch {0 1} repeat ] readonly
  706.      } ifelse
  707.   } bind
  708.   /Separation { pop //01_1 } bind
  709.   /DeviceN {
  710.     1 oget length [ exch {0 1} repeat ] readonly
  711.   } bind
  712.   /Indexed {
  713.     pop [ 0 1 BitsPerComponent bitshift 1 sub ]
  714.   } bind
  715. .dicttomark readonly def
  716.  
  717. /checkaltimage {    % <resdict> checkaltimage <resdict[']>
  718.   Printed {
  719.     dup /Alternates knownoget {
  720.       {
  721.     dup /DefaultForPrinting knownoget {
  722.       {
  723.         /Image oget exch pop exit
  724.       } {
  725.         pop
  726.       } ifelse
  727.     } {
  728.       pop
  729.     } ifelse
  730.       } forall
  731.     } if
  732.   } if
  733. } bdef
  734.  
  735. /makeimagedict {    % <resdict> <newdict> makeimagedict <imagemask>
  736.             % On return, newdict' is currentdict
  737.   begin
  738.   /Width 2 copy oget def
  739.   /Height 2 copy oget def
  740.   /BitsPerComponent 2 copy oget def
  741.   /Interpolate 2 copy knownoget { def } { pop } ifelse
  742.   makeimagekeys
  743. } bdef
  744. /makeimagekeys {    % <resdict> makeimagekeys <imagemask>
  745.         % newdict is currentdict
  746.         % Assumes Width, Height, BPC, Interpolate already copied.
  747.   /ImageType 1 def
  748.   /ImageMatrix Width 0 0
  749.         % Handle 0-height images specially.
  750.     Height dup 0 eq { pop 1 } if neg 0 1 index neg
  751.     6 array astore def
  752.   dup /ImageMask knownoget dup { and } if {
  753.         % Image mask
  754.         % Decode is required for the PostScript image operators.
  755.                 % AI8 writes bogus decode array [0 1 0 0 0 0 0 0]
  756.     /Decode 2 copy knownoget { 0 2 getinterval } { //01_1 } ifelse def
  757.         % BitsPerComponent may be missing for masks.
  758.         % The spec requires it, but some producers omit it, and
  759.         % Acrobat Reader doesn't care.
  760.     /BitsPerComponent 2 copy known { pop } { 1 def } ifelse
  761.     true
  762.   } {
  763.         % Opaque image
  764.     dup /ColorSpace oget resolvecolorspace /ColorSpace exch def
  765.         % Decode is required for the PostScript image operators.
  766.     /Decode 2 copy knownoget not {
  767.       ColorSpace //defaultdecodedict
  768.       ColorSpace dup type /arraytype eq { 0 get } if get exec
  769.     } if def
  770.     false
  771.   } ifelse
  772.         % Even though we're going to read data,
  773.         % pass false to resolvestream so that
  774.         % it doesn't try to use Length (which may not be present).
  775.   exch false resolvestream /DataSource exch def
  776. } bdef
  777.  
  778. /DoImage {
  779.   checkaltimage dup length 6 add dict
  780.   1 index /SMask knownoget { 1 index exch /SMask exch put } if
  781.   1 index /Mask knownoget { 1 index exch /Mask exch put } if
  782.   makeimagedict doimage
  783. } bdef
  784. /makemaskimage {    % <datasource> <imagemask> <Mask> makemaskimage
  785.             %   <datasource> <imagemask>, updates currentdict =
  786.             %   imagedict
  787.   dup type /arraytype eq {
  788.     /ImageType 4 def
  789.     /MaskColor exch def
  790.   } {
  791.         % Mask is a stream, another Image XObject.
  792.         % Stack: datasource imagemask(false) maskstreamdict
  793.     PDFfile fileposition exch
  794.     dup length dict makeimagedict pop
  795.         % In order to prevent the two data sources from being
  796.         % aliased, we need to make at least one a reusable stream.
  797.         % We pick the mask, since it's smaller (in case we need to
  798.         % read all its data now).
  799.         % Stack: datasource imagemask(false) savedpos
  800.         % maskdict is currentdict
  801.     /DataSource DataSource mark
  802.       /Intent 1
  803.       /AsyncRead true
  804.     .dicttomark .reusablestreamdecode def
  805.     PDFfile exch setfileposition
  806.     currentdict end currentdict end
  807.     5 dict begin
  808.     /ImageType 3 def
  809.     /InterleaveType 3 def
  810.     /DataDict exch def
  811.     /MaskDict exch def
  812.     /ColorSpace DataDict /ColorSpace get def
  813.   } ifelse
  814. } bdef
  815. /doimage {    % <imagemask> doimage -
  816.         % imagedict is currentdict, gets popped from dstack
  817.   DataSource exch
  818.   PDFversion 1.4 ge { currentdict /SMask knownoget } { false } ifelse {
  819.     makesoftmaskimage
  820.   } {
  821.     currentdict /Mask knownoget {
  822.       makemaskimage
  823.     } if
  824.   } ifelse
  825.         % Stack: datasource imagemask
  826.    % image and imagemask can be redefined in gs_init.ps to tweak interpolation
  827.    % after device-specific files are run. Don't bind them here.
  828.    { currentdict end setfillstate /imagemask }
  829.    { ColorSpace setcolorspace currentdict end setfillblend /image }
  830.   ifelse
  831.   .systemvar exec
  832.    
  833.         % Close the input stream, unless it is PDFfile or
  834.         % PDFsource.
  835.   dup dup PDFfile eq exch PDFsource eq or { pop } { closefile } ifelse
  836. } bdef
  837.  
  838. /.paintform {    % <formdict> <resdict> <stream> .paintform -
  839.   3 -1 roll dup /Group known {
  840.     .paintgroupform
  841.   } {
  842.     pop pdfopdict .pdfruncontext
  843.   } ifelse
  844. } bdef
  845.  
  846. /DoForm {
  847.     % Adobe 2nd edition of the PDF 1.3 spec makes /FormType
  848.     % and /Matrix keys optional. Cope with the missing keys.
  849.   dup length
  850.   1 index /Matrix known
  851.     { dict
  852.     }
  853.     { 1 add dict
  854.       dup /Matrix { 1 0 0 1 0 0 } cvlit put
  855.     }
  856.   ifelse
  857.   copy
  858.   dup /FormType known not {
  859.     dup length 1 add dict copy dup /FormType 1 put
  860.   } if
  861.  
  862.   dup [ 2 index /Resources knownoget { oforce } { 0 dict } ifelse
  863.   3 index false /resolvestream cvx
  864.   /.paintform cvx
  865.   ] cvx /PaintProc exch put
  866.   execform
  867. } bdef
  868.  
  869. /DoPS {
  870.   true resolvestream cvx exec
  871. } bdef
  872.  
  873. drawopdict begin
  874.   /Do {
  875.     setfillblend
  876.     PDFfile fileposition exch
  877.     dup Page /XObject rget { 
  878.       exch pop dup /Subtype get xobjectprocs exch get
  879.         % Don't leave extra objects on the stack while executing
  880.         % the definition of the form.
  881.       3 -1 roll 2 .execn
  882.     } {
  883.         % This should cause an error, but Acrobat Reader can
  884.         % continue, so we do too.
  885.       (%stderr) (w) file
  886.       dup (****************Undefined XObject resource: ) writestring 
  887.       dup 3 -1 roll write===
  888.       flushfile
  889.     } ifelse
  890.     PDFfile exch setfileposition
  891.   } bdef
  892. end
  893.  
  894. % ---------------- In-line images ---------------- %
  895.  
  896. % Undo the abbreviations in an in-line image dictionary.
  897. % Note that we must look inside array values.
  898. % /I is context-dependent.
  899. /unabbrevkeydict mark
  900.   /BPC /BitsPerComponent  /CS /ColorSpace  /D /Decode  /DP /DecodeParms
  901.   /F /Filter  /H /Height  /I /Interpolate  /IM /ImageMask  /W /Width
  902. .dicttomark readonly def
  903. /unabbrevvaluedict mark
  904.   /AHx /ASCIIHexDecode  /A85 /ASCII85Decode  /CC /CalCMYK
  905.   /CCF /CCITTFaxDecode  /CG /CalGray  /CR /CalRGB
  906.   /DCT /DCTDecode  /CMYK /DeviceCMYK  /Fl /FlateDecode
  907.   /G /DeviceGray  /RGB /DeviceRGB
  908.   /I /Indexed  /LZW /LZWDecode  /RL /RunLengthDecode
  909. .dicttomark readonly def
  910. /unabbrevtypedict mark
  911.   /nametype {
  912.     //unabbrevvaluedict 1 index .knownget { exch pop } if
  913.   }
  914.   /arraytype {
  915.     dup 0 1 2 index length 1 sub {
  916.       2 copy get unabbrevvalue put dup
  917.     } for pop
  918.   }
  919. .dicttomark readonly def
  920. /unabbrevvalue {    % <obj> unabbrevvalue <obj'>
  921.   oforce //unabbrevtypedict 1 index type .knownget { exec } if
  922. } bdef
  923.  
  924. drawopdict begin
  925.   /BI { mark } bdef
  926.   /ID {
  927.     counttomark 2 idiv dup 6 add dict begin {
  928.       exch //unabbrevkeydict 1 index .knownget { exch pop } if
  929.       exch unabbrevvalue def
  930.     } repeat pop
  931.     /File PDFsource def
  932.     currentdict makeimagekeys doimage    
  933.     % The Adobe documentation says that the data following ID
  934.     % consists of "lines", and some PDF files (specifically, some files
  935.     % produced by PCL2PDF from Visual Software) contain garbage bytes
  936.     % between the last byte of valid data and an EOL.
  937.         % Some files (PDFOUT v3.8d by GenText) have EI immediately following
  938.         % the stream. Some have no EOL and garbage bytes.
  939.         % Therefore, we skip all bytes before EI or EOL 
  940.     0
  941.       { PDFsource read not { //true exit } if
  942.         dup 10 eq 1 index 13 eq or
  943.           { pop PDFsource token pop /EI ne exit
  944.           }
  945.         if
  946.         exch 69 eq 1 index 73 eq and { //false exit } if  % 'EI'
  947.       }
  948.     loop
  949.     exch pop
  950.       { /ID cvx /syntaxerror signalerror
  951.       }
  952.     if
  953.   } bdef
  954. end
  955.  
  956. % ================================ Text ================================ %
  957.  
  958. drawopdict begin
  959.             % Text control
  960.   /BT { BT } def
  961.   /ET { ET } def
  962.   /Tc { Tc } def
  963.   /TL { TL } def
  964.   /Tr { Tr } def
  965.   /Ts { Ts } def
  966.   /Tw { Tw } def
  967.   /Tz { Tz } def
  968.             % Text positioning
  969.   /Td { Td } def
  970.   /TD { TD } def
  971.   /Tm { Tm } def
  972.   /T* { T* } def
  973.             % Text painting
  974.   /Tj { Tj } def
  975.   /' { ' } def
  976.   /" { " } def
  977.   /TJ { TJ } def
  978. end
  979.  
  980. % ============================== Annotations ============================== %
  981.  
  982.  
  983.  
  984. % Get and normalize an annotation's rectangle.
  985. /annotrect {        % <annot> annotrect <x> <y> <w> <h>
  986.   /Rect get aload pop
  987.   exch 3 index sub dup 0 lt { dup 5 -1 roll add 4 1 roll neg } if
  988.   exch 2 index sub dup 0 lt { dup 4 -1 roll add 3 1 roll neg } if
  989. } bdef
  990.  
  991. % Set an annotation color.
  992. /annotsetcolor {    % <annot> annotsetcolor -
  993.   /C knownoget { aload pop setrgbcolor } { 0 setgray } ifelse
  994. } bdef
  995.  
  996. % Draw the border.  Currently, we ignore requests for beveling, and we
  997. % don't round the corners of rectangles.
  998. /strokeborder {        % <annot> <width> <dash> strokeborder -
  999.   1 index 0 ne {    % do not draw if border width is 0
  1000.     gsave
  1001.     2 index annotsetcolor
  1002.     0 setdash dup setlinewidth
  1003.     exch annotrect
  1004.     2 { 4 index sub 4 1 roll } repeat
  1005.     2 { 4 index 0.5 mul add 4 1 roll } repeat
  1006.     rectstroke pop
  1007.     grestore
  1008.   } {
  1009.     pop pop pop
  1010.   } ifelse
  1011. } bdef
  1012.  
  1013. % Draw an annotation border.
  1014. /drawborder {        % <annot> drawborder -
  1015.   gsave
  1016.   dup /BS knownoget {
  1017.     dup /W knownoget not { 1 } if
  1018.     [] 2 index /S knownoget {
  1019.       /D eq { 2 index /D knownoget not { [3] } if exch pop } if
  1020.     } if 3 -1 roll pop strokeborder
  1021.   } {
  1022.     dup /Border knownoget {
  1023.       dup 2 get
  1024.       exch dup length 3 gt { 3 get } { pop [] } ifelse
  1025.       strokeborder
  1026.     } {
  1027.       pop
  1028.     } ifelse
  1029.   } ifelse
  1030.   grestore
  1031. } bdef
  1032.  
  1033. %
  1034. %   The PDF annotation F (flags) integer is bit encoded.
  1035. %   Bit 1 (LSB) Invisible:  1 --> Do not display if no handler.
  1036. %         Note:  We have no handlers but we ignore this bit.
  1037. %   Bit 2 Hidden:  1 --> Do not display.  We will not display if this bit is set.
  1038. %   Bit 3 Print:  1 --> Display if printing.  We will display if this bit set
  1039. %         (and not hidden) and Printed is true
  1040. %   Bit 4 NoZoom:  1 --> Do not zoom annotation even if image is zoomed.
  1041. %   Bit 5 NoRotate:  1 --> Do not rotate annotation even if image is rotated.
  1042. %   Bit 6 NoView:  0 --> Display if this is a 'viewer'.  We will display
  1043. %         if this bit is not set (and not hidden) and Printed is false
  1044. %   Bit 7 Read Only - 1 --> No interaction.  We ignore this bit
  1045. %
  1046. /annotvisible {            % <annot> annotvisible <visible>
  1047.   /F knownoget not { 0 } if         % Get flag value
  1048.   dup 2 and 0 eq              % Check hidden flag
  1049.   exch dup 4 and 0 ne Printed and    % Check print flag
  1050.   exch 64 and 0 eq Printed not and    % Check noview flag
  1051.   or                    % Combine print and view
  1052.   and                     % Combine with 'hidden' flag test
  1053. } bdef
  1054.  
  1055. /drawwidget {            % <scalefactor> <annot> drawwidget -
  1056.   dup /AP knownoget {
  1057.     % Always use the Normal appearance.
  1058.     /N oget
  1059.         % Acrobat Distiller produces files in which this Form
  1060.         % XObject lacks Type and Subtype keys.  This is illegal,
  1061.         % but Acrobat Reader accepts it.  The only way we can
  1062.         % tell whether this is a Form or a set of sub-appearances
  1063.         % is by testing for the stream Length key.
  1064.     dup /Length known {
  1065.               % If this is a form then simply use it
  1066.       true
  1067.     } {
  1068.       1 index /AS knownoget not {
  1069.               % If we do not have AS then use any appearance
  1070.     { exch pop oforce exit } forall true
  1071.       } { 
  1072.         % Stack: annot Ndict AS
  1073.         % Get the specified appearance.  If no appearance, then
  1074.         % display nothing - set stack = false.
  1075.     knownoget
  1076.       } ifelse
  1077.     } ifelse
  1078.  
  1079.         % Stack: scale annot appearance true
  1080.         % Stack: scale annot false
  1081.     {
  1082.               % Draw appearance
  1083.       1 index annotrect pop pop translate
  1084.       2 index dup scale        % Apply scale factor
  1085.       DoForm
  1086.     } if
  1087.   } if pop pop
  1088. } bdef
  1089.  
  1090. %
  1091. %  For stamp object we have to determine the size of the output rectangle
  1092. %  and the size of the BBox for the stamp image.  From these we calculate
  1093. %  a scale factor for drawing the stamp.
  1094. %
  1095. /calcstampscale {        % <annot> calcstampscale scale
  1096.   dup annotrect 4 -2 roll pop pop pop    % get x width
  1097.   dup 0 lt { neg } if        % get magnitude
  1098.   exch /AP knownoget {
  1099.     /N knownoget {
  1100.       /BBox knownoget {
  1101.          aload pop 4 -2 roll pop pop pop
  1102.          div
  1103.       } {
  1104.         pop 1            % default to unity scaling
  1105.       } ifelse            % if we have /BBox
  1106.     } {
  1107.       pop 1
  1108.     } ifelse            % if we have /N
  1109.   } {
  1110.     pop 1
  1111.   } ifelse            % if we have /AP
  1112. } bdef
  1113.  
  1114. /drawlink {            % <annot> drawlink -
  1115.   dup drawborder
  1116.   1 exch drawwidget
  1117. } bdef
  1118.  
  1119. % Draw an annotation.
  1120. /drawannottypes mark
  1121.   /Link { drawlink } bind
  1122.   /Stamp { dup calcstampscale exch drawwidget } bind
  1123. .dicttomark readonly def
  1124. /drawannot {        % <annot> drawannot -
  1125.   dup annotvisible {
  1126.     gsave
  1127.     dup dup /Subtype get //drawannottypes exch .knownget {
  1128.       exec
  1129.     } {
  1130.       1 exch drawwidget        % Use drawwidget for everything else
  1131.     } ifelse            % type known
  1132.     grestore
  1133.   } if pop            % annotvisible
  1134. } bdef
  1135. currentdict /drawannottypes undef
  1136.  
  1137. end            % pdfdict
  1138. end            % GS_PDF_ProcSet
  1139. .setglobal
  1140.